/*
 * test_memdiff.cpp
 *
 *  Created on: Jun 19, 2014
 *      Author: killerg
 */

#include <event2/util.h>
#include "share/clock.h"

#include <assert.h>
#include <vector>
#include <map>
#include <string.h>

using namespace std;

const size_t evnum = (120*4+10*8 + 50*4 * 50) * 2;
const size_t frinum = evnum / 4;


#define MODIFYT(ptr, field, val, patches) {	\
		pair<uint32_t,uint32_t> ___patch;	\
		___patch.first = (uint8_t*)&(ptr)->field - (uint8_t*)(ptr);	\
		___patch.second = sizeof((ptr)->field);	\
		(ptr)->field = val;	\
		(patches).push_back(___patch);	\
	}

#define MODIFYB(ptr, off, val, patches) {	\
		pair<uint32_t,uint32_t> ___patch;	\
		___patch.first = off;	\
		___patch.second = sizeof(val);	\
		ptr[off] = val;	\
		patches.push_back(___patch);	\
	}


void patch(void* vfrom, void* vto, uint32_t size, vector<pair<uint32_t, uint32_t>> &patches) {
	uint8_t* from = (uint8_t*)vfrom;
	uint8_t* to = (uint8_t*)vto;
	for (auto &patch : patches) {
		memcpy(to + patch.first, from + patch.first, patch.second);
	}
}

void diff(void* vfrom, void* vto, uint32_t size, vector<pair<uint32_t, uint32_t>> &patches) {
	uint8_t* from = (uint8_t*)vfrom;
	uint8_t* to = (uint8_t*)vto;

	pair<uint32_t, uint32_t> patch(-1,0);

	for (int i=0; i<size; ++i) {
		if (from[i] != to[i]) {
			if (patch.first == -1)
				patch.first = i;
			patch.second++;
		} else {
			if (patch.first != -1) {
				patches.push_back(patch);
				patch.first = -1;
				patch.second = 0;
			}
		}
	}
}

struct equip_t {
	int pos;
	int star;
};

struct player_t {
	int32_t id;
	int32_t friends[10];
	equip_t equips[20];
};

typedef vector<pair<uint32_t, uint32_t>> patch_t;

const int32_t testnum = 10000;

bool test_memdiff() {
#if 0
	auto players = new player_t[testnum];
	auto tos = new player_t[testnum];

	auto patches = new patch_t[testnum];

	double start = my_clock_t::get_time();
	for (int i=0; i<testnum; ++i) {
		for (int ii=0; ii<10; ++ii) {
			MODIFYT(players+i, friends[rand()%frinum], ii, patches[i]);
			//(players+i)->friends[rand()%frinum] = ii;
		}
	}
	printf("%f\n", my_clock_t::get_time() - start);

	start = my_clock_t::get_time();

	for (int i=0; i<testnum; ++i) {
		::patch(players+i, tos+i, sizeof(player_t), patches[i]);
	}

	printf("%d %d %f\n", sizeof(player_t)*testnum, sizeof(player_t), my_clock_t::get_time() - start);

	delete[] patches;

	delete[] tos;
	delete[] players;

#endif

	player_t player = {};
	player_t to = {};

	patch_t patch;
	for (int i=0; i<10; ++i) {
		int rnd = rand();
		equip_t equip = {i, rnd};
		MODIFYT(&player, equips[rnd%20], equip, patch);
	}

	assert(memcmp(&to, &player, sizeof(player)) != 0);

	::patch(&player, &to, sizeof(player), patch);

	assert(memcmp(&to, &player, sizeof(player)) == 0);

	return true;
}
